package com.security.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.security.entity.AppInfo;
import com.security.mapper.AppInfoMapper;
import com.security.service.AppInfoIService;
import com.security.tools.RedisUtil;
import com.security.vo.AccessToken;
import com.security.vo.RestfulDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.UUID;

/**
 * Package: com.security.service.impl
 * Description：
 * Author: huangjian
 * Date:  2020/9/16 14:53
 * Modified By:
 *
 * @author huangjian
 */
@Component
public class AppInfoServiceImpl extends ServiceImpl<AppInfoMapper, AppInfo> implements AppInfoIService {

    private static final int EXPIRES = 2 * 60 * 60;
    @Resource
    private RedisUtil redisUtil;

    private AppInfo getOne(String accessToken) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("acess_token", accessToken);
        return baseMapper.selectOne(queryWrapper);
    }


    @Override
    public AppInfo getOneByAppId(String appId) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("app_id", appId);
        return baseMapper.selectOne(queryWrapper);
    }

    private AppInfo getOne(String appId, String appSecret) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("app_id", appId);
        queryWrapper.eq("app_secret", appSecret);
        return baseMapper.selectOne(queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public RestfulDTO getAccessToken(String appId, String appSecret) {
        if (Objects.isNull(appId)) {
            return RestfulDTO.fail("appId参数不能为空");
        }
        if (Objects.isNull(appSecret)) {
            return RestfulDTO.fail("appSecret参数不能为空");
        }
        AppInfo appInfo = getOne(appId, appSecret);
        if (Objects.isNull(appInfo)) {
            return RestfulDTO.fail("app信息不存在");
        }
        if (appInfo.getIsDel()) {
            return RestfulDTO.fail("app已停止合作");
        }

        String accessTokenLast = appInfo.getAccessToken();
        if (StringUtils.isNotEmpty(accessTokenLast)) {
            if (redisUtil.exists(accessTokenLast)) {
                //如果存在，则从缓存里面拿到返回
                AccessToken accessToken = new AccessToken();
                accessToken.setAccessToken(accessTokenLast);
                accessToken.setExpiresIn(redisUtil.ttl(accessTokenLast));
                accessToken.setRefreshToken(appInfo.getRefreshToken());
                return RestfulDTO.success(accessToken);
            }
            //如果不存在，则走重新生成逻辑
            //删掉最近的accessToken
            redisUtil.delete(accessTokenLast);
        }
        String access_token = UUID.randomUUID().toString().replace("-", "");
        String refresh_token = UUID.randomUUID().toString();

        redisUtil.set(access_token, appId, EXPIRES);
        redisUtil.set(refresh_token, access_token, EXPIRES);

        appInfo.setAccessToken(access_token);
        appInfo.setRefreshToken(refresh_token);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("app_id", appId);
        queryWrapper.eq("app_secret", appSecret);
        int update = baseMapper.update(appInfo, queryWrapper);
        if (update < 0) {
            return RestfulDTO.fail("生成token失败");
        }
        AccessToken accessToken = new AccessToken();
        accessToken.setAccessToken(access_token);
        accessToken.setExpiresIn(EXPIRES);
        accessToken.setRefreshToken(refresh_token);
        return RestfulDTO.success(accessToken);
    }

    @Override
    public RestfulDTO refreshAccessToken(String refresh_token) {
        if (StringUtils.isEmpty(refresh_token)) {
            return RestfulDTO.fail("refresh_token is required");
        }
        if (!redisUtil.exists(refresh_token)) {
            return RestfulDTO.fail("refresh_token is valid");
        }
        String access_token = redisUtil.get(refresh_token);
        if (!redisUtil.exists(access_token)) {
            return RestfulDTO.fail("access_token is valid");
        }
        String appId = redisUtil.get(access_token);
        AppInfo appInfo = getOneByAppId(appId);
        if (Objects.isNull(appInfo)) {
            return RestfulDTO.fail("access_token is valid");
        }
        if (appInfo.getIsDel()) {
            return RestfulDTO.fail("合作关系未建立");
        }
        if (StringUtils.isNotEmpty(appInfo.getAccessToken())) {
            //删掉最近的accessToken
            redisUtil.delete(appInfo.getAccessToken());
        }

        if (StringUtils.isNotEmpty(appInfo.getRefreshToken())) {
            //删掉最近的refresh_token
            redisUtil.delete(appInfo.getRefreshToken());
        }

        String new_access_token = UUID.randomUUID().toString().replace("-", "");
        String new_refresh_token = UUID.randomUUID().toString();

        redisUtil.set(new_access_token, appId, EXPIRES);
        redisUtil.set(new_refresh_token, new_access_token, EXPIRES);

        appInfo.setAccessToken(new_access_token);
        appInfo.setRefreshToken(new_refresh_token);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("refresh_token", refresh_token);

        int update = baseMapper.update(appInfo, queryWrapper);
        if (update < 0) {
            return RestfulDTO.fail("刷新token失败");
        }
        AccessToken accessToken = new AccessToken();
        accessToken.setAccessToken(new_access_token);
        accessToken.setExpiresIn(EXPIRES);
        accessToken.setRefreshToken(new_refresh_token);
        return RestfulDTO.success(accessToken);
    }
}
